home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
me_cd25.zip
/
DOC.ZIP
/
INSIDEMU
< prev
next >
Wrap
Text File
|
1992-11-09
|
6KB
|
194 lines
-*-text-*-
Inside Mutt
------ ----
Notes on what goes on under the hood of an embedded language.
Overview of Embedded Languages
-------- -- -------- ---------
Why embedded languages are cool
Why you want one in your application
- less code to debug, just need a core "machine"
- easier to expand
- same extension language in all your applications
Typed (kinda), why: runtime error checking
Compiled. why: static checking and speed
Algol like
Stack based
procedure called based
"Loosely" coupled with application:
Standalone language
Don't know much about the application
General purpose - never will know much about application
Has "library" (mmaux.c) that has functions used to interface with
application.
This makes it very easy to add Mutt to about any application.
Drawbacks:
Hard for Joe Average-Application-User to modify.
Internal Objects
-------- -------
Characteristics:
Mutt knows everything there is to know about these objects.
Should act like regular vars - globals live as long as the block,
locals come and go with a stack frame.
Since objects are [big] structs and might be used in outside
libraries, they can be a pain:
- MC has know to deal with them. This can be rude from the machine
independent aspect.
- It can be a pain to dig and reassemble the struct from a chunk of
memory. Can't use C to just stuff it or retrieve because
different machines require more/less space and different
alignments. To do that would require MC to know the biggest the
struct could ever be as well as the worst case alignment.
Might be easier to add special instructions for each object and keep
some kind of numeric id in var memory and have separate areas and
code to maintain them.
Pro:
- MC just thinks of objects as numbers.
-
Con:
- Not as easy to control stack growth. More work to sync it with
var stack.
- Yet more stacks to control, more memory being used up.
- More opcodes.
How To:
- Local:
- (create-local-objects n): Create n objects for use in current
stack frame. Have to remember where previous stack frame
starts. This can be stored in the var stack frame. Have to
remember where this frame starts.
- (free-local-objects): Free all objects in the current stack
frame.
- (gc-local-objects): Free all local objects.
- (set-local-object n): Set the nth object in the current stack
frame.
- (get-local-object n): Get the nth object in the current stack
frame.
- Global:
- (create-global-object n offset-1 ... offset-n): Create n
objects as global objects. Store their ids in offset-i.
- (free-global-object offset): Free the object whos id is stored
in offset.
- (gc-global-objects block): Free all objects associated with
block. This probably just entails calling the block prologue.
- (set-global-object offset): Set the object whos id is stored in
offset.
- (get-global-object offset): Get the object whos id is stored in
offset.
EG: dStrings
Constructors
Destructors
Local Objects
garbage collection if program aborts
prologue
epilogue
Global
garbage collection if block is removed
prologue
epilogue
Wants:
Want fast allocate/free for (at least) local objects
Need to gc all local objects in event of abort, without knowing
anything except that they are local.
Need to be able to gc all objects if a block is freed. Do this by
calling the block epilogue.
External Objects
-------- -------
Characteristics:
Don't know what they are
Don't know how to GC them
Allocated by external source, I just have an id
EG Buffers
How created
How freed
How GCed in case of problems
Global vs local
Garbage Collection for Embedded Systems
------- ---------- --- -------- -------
Need GC because:
If a programs tanks, all the objects allocated so far won't be freed.
Less for the programmer to worry about or forget.
Programmers are bound to forget a few frees and never notice.
Mutt strings.
Domains:
Internal Mutt:
dStrings.
OOP: Probably don't need gc - constructors and destructors can
handle the normal cases. GC is needed for when the program is
aborted.
External Mutt:
Objects can be allocated that Mutt will never know how to deal with.
For example: Bags, Marks, Buffers.
Constraints:
Don't want to slow down programs.
Solutions:
Internal:
Pool strings so can gc on abort or program termination. Handle like
external objects (or OOP):
{
(string foo bar)
(foo "this is a test")
(done)
(bar foo)
}
generates code:
{
(int foo bar)
(foo (create-string)) (bar (create-string))
(copy-to-string foo "this is a test") ;; (foo "this is a test")
(goto gc-strings) ;; (done)
(copy-to-string bar (get-string foo)) ;; (bar foo)
(label gc-strings)
(free-string foo bar)
(done)
}
Need new ops:
(create-string [global]) ;; RV gets string id
(copy-to-string string-id text) ;; RV gets texts, put in string
(get-string string-id) ;; RV gets char *
(free-string id) ;;
Global strings:
Need global strings so have 2 pools - Mortal and Immortal. No id
overlap!
External:
When external objects are allocated, they are flagged Mortal or
Immortal. When a program stops running or aborts,
MMgc_foreign_objects() is called. The external "process" can then
sweep the object lists and remove all objects marked Mortal.
Pros:
Easy. Doesn't slow program execution.
Cons:
Not real GC. If the programmer is lazy and doesn't free stuff, it
could be while before the resources are freed (programs that
repeatedly call a routine that creates objects).
Mutt Machine
---- -------
Instructions
Never ment to be compiled down to machine language
Tradeoffs: small memory used, tagged, high level, portable.
problems:
reading/writing numbers: byte order, alignment